// src/directives/debounce.ts
import {
  DirectiveBinding,
  ObjectDirective,
  App,
  ComponentInternalInstance,
  getCurrentInstance,
} from "vue";

/**
 * 防抖函数
 * @param fn 要执行的函数
 * @param delay 延迟时间(毫秒)
 * @returns 防抖处理后的函数
 */
function debounce<T extends (...args: any[]) => any>(fn: T, delay = 500): T {
  let timer: ReturnType<typeof setTimeout> | null = null;
  return function (this: any, ...args: Parameters<T>) {
    if (timer) clearTimeout(timer);
    timer = setTimeout(() => {
      fn.apply(this, args);
      timer = null;
    }, delay);
  } as T;
}

interface DebounceElement extends HTMLElement {
  _debouncedFn?: (() => void) | EventListener;
}

/**
 * 修正后的防抖指令绑定接口
 * 使用 Record<string, boolean> 替代 DirectiveModifiers
 */
interface DebounceBinding extends Omit<DirectiveBinding, "modifiers"> {
  value: (...args: any[]) => any;
  arg?: string;
  modifiers?: Record<string, boolean>;
}

/**
 * 防抖指令
 */
export const vDebounce: ObjectDirective<DebounceElement, () => void> = {
  mounted(el, binding: DebounceBinding) {
    const { value, arg } = binding;
    const delay = arg ? parseInt(arg) : 500;

    // 处理函数调用情况
    const fn = typeof value === "function" ? value : () => value;

    el._debouncedFn = debounce(fn, delay);
    el.addEventListener("click", el._debouncedFn);
  },
  beforeUnmount(el) {
    if (el._debouncedFn) {
      el.removeEventListener("click", el._debouncedFn as EventListener);
    }
  },
};

/**
 * 全局注册防抖指令
 * @param app Vue应用实例
 */
export function setupDebounceDirective(app: App) {
  app.directive("debounce", vDebounce);
}

declare module "@vue/runtime-core" {
  export interface GlobalDirectives {
    vDebounce: typeof vDebounce;
  }
}
